package com.hdhere.domain.common.data;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

/**
 * Created by dus on 2018/11/4.
 */
public class JsonUserType implements UserType, ParameterizedType {

    private static Logger logger = LoggerFactory.getLogger(JsonUserType.class);

    private String entityClass;

    @Override
    public int[] sqlTypes() {

        return new int[] {Types.JAVA_OBJECT};
    }

    @Override
    public Class returnedClass() {

        return Object.class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {

        if (x == null) {

            return y == null;
        }

        return x.equals(y);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {

        return x.hashCode();
    }

//    @Override
//    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
//            throws HibernateException, SQLException {
//
//        if (rs.getString(names[0]) == null) {
//            return null;
//        }
//        try {
//            return JSON.parseObject(rs.getBytes(names[0]), Class.forName(this.entityClass));
//        }
//        catch (Exception e) {
//            logger.error(e.getMessage(), e);
//            return null;
//        }
//    }
//
//    @Override
//    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
//            throws HibernateException, SQLException {
//
//        if (value == null) {
//            st.setNull(index, Types.BLOB);
//            return;
//        }
//        st.setNString(index, JSON.toJSONString(value, SerializerFeature.WriteNonStringKeyAsString));
//        // setBytes(index, JSON.toJSONBytes(value));
//    }
    @Override
    public Object nullSafeGet(ResultSet resultSet, String[] name, SharedSessionContractImplementor sharedSessionContractImplementor, Object owner) throws HibernateException, SQLException {

        if (resultSet.getString(name[0]) == null) {
            return null;
        }
        try {
            return JSON.parseObject(resultSet.getBytes(name[0]), Class.forName(this.entityClass));
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    @Override
    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
        if (value == null) {
            preparedStatement.setNull(index, Types.BLOB);
            return;
        }
        preparedStatement.setNString(index, JSON.toJSONString(value, SerializerFeature.WriteNonStringKeyAsString));
        // setBytes(index, JSON.toJSONBytes(value));
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {

        return value;
    }

    @Override
    public boolean isMutable() {

        return true;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {

        return (String) this.deepCopy(value);
    }

    @Override
    public Object assemble(Serializable cached, Object owner) throws HibernateException {

        return this.deepCopy(cached);
    }

    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {

        return original;
    }

    @Override
    public void setParameterValues(Properties parameters) {

        this.entityClass = parameters.getProperty("class", "java.lang.String");
    }
}
